package com.joy.practice.server;

import com.joy.practice.server.codec.OrderFrameDecoder;
import com.joy.practice.server.codec.OrderFrameEncoder;
import com.joy.practice.server.codec.OrderProtocolDecoder;
import com.joy.practice.server.codec.OrderProtocolEncoder;
import com.joy.practice.server.handler.MetricHandler;
import com.joy.practice.server.handler.OrderServerProcessHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.concurrent.DefaultThreadFactory;

import java.util.concurrent.ExecutionException;

public class Server {

    public static void main(String[] args) {
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        NioEventLoopGroup boss = new NioEventLoopGroup(0, new DefaultThreadFactory("server-boss"));
        NioEventLoopGroup worker = new NioEventLoopGroup(0, new DefaultThreadFactory("server-worker"));
        MetricHandler handler = new MetricHandler();

        try {
            serverBootstrap.channel(NioServerSocketChannel.class)
                    .group(boss, worker)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ChannelInitializer<NioSocketChannel>() {
                        @Override
                        protected void initChannel(NioSocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            pipeline.addLast("frameDecoder", new OrderFrameDecoder());
                            pipeline.addLast("frameEncoder", new OrderFrameEncoder());
                            pipeline.addLast("protocolEncoder", new OrderProtocolEncoder());
                            pipeline.addLast("protocolDecoder", new OrderProtocolDecoder());
                            pipeline.addLast(new LoggingHandler(LogLevel.INFO));
                            pipeline.addLast("metricHandler", handler);
                            pipeline.addLast(new OrderServerProcessHandler());
                        }
                    });

            ChannelFuture future = serverBootstrap.bind(8090).sync();
            future.channel().closeFuture().get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        } finally {
            boss.shutdownGracefully();
        }
    }

}
